"""交易数据模型"""

from datetime import datetime
from typing import Dict, Any, Optional
from pymongo.collection import Collection
from bson import ObjectId
import json

class TransactionModel:
    """交易数据模型类
    
    负责:
    1. 交易数据的持久化
    2. 交易信息的查询
    3. 交易状态的管理
    """
    
    def __init__(self, mongo_db):
        self.db = mongo_db
        self.transactions_collection: Collection = mongo_db.transactions
        
        # 创建索引
        self._create_indexes()
    
    def _create_indexes(self):
        """创建数据库索引"""
        try:
            # 为tx_hash创建唯一索引
            self.transactions_collection.create_index(
                "tx_hash", 
                unique=True, 
                name="tx_hash_unique"
            )
            
            # 为chain_type创建索引
            self.transactions_collection.create_index(
                "chain_type", 
                name="chain_type_index"
            )
            
            # 为timestamp创建索引
            self.transactions_collection.create_index(
                "timestamp", 
                name="timestamp_index"
            )
            
            # 为contract_address创建索引
            self.transactions_collection.create_index(
                "contract_address", 
                name="contract_address_index"
            )
            
            # 复合索引：chain_type + timestamp
            self.transactions_collection.create_index(
                [("chain_type", 1), ("timestamp", -1)], 
                name="chain_timestamp_index"
            )
            
        except Exception as e:
            print(f"创建交易索引失败: {e}")
    
    def save_transaction(self, tx_hash: str, chain_type: str, 
                        contract_address: str, method: str, 
                        params: Dict[str, Any], result: Dict[str, Any],
                        key: str = None, value: str = None) -> str:
        """保存交易信息
        
        Args:
            tx_hash: 交易哈希
            chain_type: 区块链类型
            contract_address: 合约地址
            method: 调用方法
            params: 调用参数
            result: 执行结果
            key: 设置的键（可选）
            value: 设置的值（可选）
            
        Returns:
            str: 插入的文档ID
        """
        try:
            transaction_doc = {
                "tx_hash": tx_hash,
                "chain_type": chain_type,
                "contract_address": contract_address,
                "method": method,
                "params": params,
                "result": result,
                "timestamp": datetime.utcnow(),
                "created_at": datetime.utcnow(),
                "status": "completed"
            }
            
            # 如果是set操作，保存key和value
            if method == "set" and key and value:
                transaction_doc["key"] = key
                transaction_doc["value"] = value
            
            # 插入文档
            insert_result = self.transactions_collection.insert_one(transaction_doc)
            return str(insert_result.inserted_id)
            
        except Exception as e:
            print(f"保存交易信息失败: {e}")
            raise
    
    def get_transaction_by_hash(self, tx_hash: str) -> Optional[Dict[str, Any]]:
        """根据交易哈希获取交易信息
        
        Args:
            tx_hash: 交易哈希
            
        Returns:
            Dict[str, Any]: 交易信息，如果不存在返回None
        """
        try:
            transaction = self.transactions_collection.find_one({"tx_hash": tx_hash})
            if transaction:
                # 转换ObjectId为字符串
                transaction["_id"] = str(transaction["_id"])
                # 转换datetime为ISO格式字符串
                if "timestamp" in transaction:
                    transaction["timestamp"] = transaction["timestamp"].isoformat()
                if "created_at" in transaction:
                    transaction["created_at"] = transaction["created_at"].isoformat()
            return transaction
            
        except Exception as e:
            print(f"查询交易信息失败: {e}")
            raise
    
    def get_transaction_by_hash_and_chain(self, tx_hash: str, chain_type: str) -> Optional[Dict[str, Any]]:
        """根据交易哈希和区块链类型获取交易信息
        
        Args:
            tx_hash: 交易哈希
            chain_type: 区块链类型
            
        Returns:
            Dict[str, Any]: 交易信息，如果不存在返回None
        """
        try:
            transaction = self.transactions_collection.find_one({
                "tx_hash": tx_hash,
                "chain_type": chain_type
            })
            if transaction:
                # 转换ObjectId为字符串
                transaction["_id"] = str(transaction["_id"])
                # 转换datetime为ISO格式字符串
                if "timestamp" in transaction:
                    transaction["timestamp"] = transaction["timestamp"].isoformat()
                if "created_at" in transaction:
                    transaction["created_at"] = transaction["created_at"].isoformat()
            return transaction
            
        except Exception as e:
            print(f"查询交易信息失败: {e}")
            raise
    
    def get_transactions_by_chain(self, chain_type: str, limit: int = 100, 
                                 skip: int = 0) -> list:
        """根据区块链类型获取交易列表
        
        Args:
            chain_type: 区块链类型
            limit: 返回数量限制
            skip: 跳过数量
            
        Returns:
            list: 交易列表
        """
        try:
            cursor = self.transactions_collection.find(
                {"chain_type": chain_type}
            ).sort("timestamp", -1).skip(skip).limit(limit)
            
            transactions = []
            for transaction in cursor:
                transaction["_id"] = str(transaction["_id"])
                if "timestamp" in transaction:
                    transaction["timestamp"] = transaction["timestamp"].isoformat()
                if "created_at" in transaction:
                    transaction["created_at"] = transaction["created_at"].isoformat()
                transactions.append(transaction)
            
            return transactions
            
        except Exception as e:
            print(f"查询交易列表失败: {e}")
            raise
    
    def get_transactions_by_contract(self, contract_address: str, 
                                   limit: int = 100, skip: int = 0) -> list:
        """根据合约地址获取交易列表
        
        Args:
            contract_address: 合约地址
            limit: 返回数量限制
            skip: 跳过数量
            
        Returns:
            list: 交易列表
        """
        try:
            cursor = self.transactions_collection.find(
                {"contract_address": contract_address}
            ).sort("timestamp", -1).skip(skip).limit(limit)
            
            transactions = []
            for transaction in cursor:
                transaction["_id"] = str(transaction["_id"])
                if "timestamp" in transaction:
                    transaction["timestamp"] = transaction["timestamp"].isoformat()
                if "created_at" in transaction:
                    transaction["created_at"] = transaction["created_at"].isoformat()
                transactions.append(transaction)
            
            return transactions
            
        except Exception as e:
            print(f"查询合约交易列表失败: {e}")
            raise
    
    def update_transaction_status(self, tx_hash: str, status: str) -> bool:
        """更新交易状态
        
        Args:
            tx_hash: 交易哈希
            status: 新状态
            
        Returns:
            bool: 更新是否成功
        """
        try:
            result = self.transactions_collection.update_one(
                {"tx_hash": tx_hash},
                {"$set": {"status": status, "updated_at": datetime.utcnow()}}
            )
            return result.modified_count > 0
            
        except Exception as e:
            print(f"更新交易状态失败: {e}")
            raise
    
    def delete_transaction(self, tx_hash: str) -> bool:
        """删除交易记录
        
        Args:
            tx_hash: 交易哈希
            
        Returns:
            bool: 删除是否成功
        """
        try:
            result = self.transactions_collection.delete_one({"tx_hash": tx_hash})
            return result.deleted_count > 0
            
        except Exception as e:
            print(f"删除交易记录失败: {e}")
            raise
    
    def get_all_transactions(self, limit: int = 100, skip: int = 0) -> list:
        """获取所有交易列表
        
        Args:
            limit: 返回数量限制
            skip: 跳过数量
            
        Returns:
            list: 交易列表
        """
        try:
            cursor = self.transactions_collection.find().sort(
                "timestamp", -1
            ).skip(skip).limit(limit)
            
            transactions = []
            for transaction in cursor:
                transaction["_id"] = str(transaction["_id"])
                if "timestamp" in transaction:
                    transaction["timestamp"] = transaction["timestamp"].isoformat()
                if "created_at" in transaction:
                    transaction["created_at"] = transaction["created_at"].isoformat()
                transactions.append(transaction)
            
            return transactions
            
        except Exception as e:
            print(f"查询所有交易失败: {e}")
            raise
    
    def get_transaction_count(self, chain_type: str = None) -> int:
        """获取交易数量
        
        Args:
            chain_type: 区块链类型（可选）
            
        Returns:
            int: 交易数量
        """
        try:
            query = {}
            if chain_type:
                query["chain_type"] = chain_type
            
            return self.transactions_collection.count_documents(query)
            
        except Exception as e:
            print(f"获取交易数量失败: {e}")
            raise